from typing import Optional
from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.fields import GenericForeignKey
from django.utils.translation import gettext_lazy as _
from django.conf import settings

class AUDIT_STATUS(models.TextChoices):
    PENDING = "pending", _("审核中")
    REJECTED = "rejected", _("审核不通过")
    APPROVED = "approved", _("审核通过")

default_audit_status_field = models.CharField(
    max_length=10,
    verbose_name=_("审核状态"),
    choices=AUDIT_STATUS.choices,
    default=AUDIT_STATUS.PENDING,
)

class AMTag(models.Model):
    name = models.CharField(max_length=100, unique=True, verbose_name=_("标签名称"))
    description = models.TextField(blank=True, verbose_name=_("描述"))
    created_at = models.DateField(auto_now_add=True)

    class Meta:
        default_permissions = []
        db_table = 'audit_tags'
        verbose_name = _('审核标签')
        verbose_name_plural = verbose_name

class AuditManagementManager(models.Manager):
    def get_for_object(self, obj, tag: Optional[str] = None):
        """
        Get audit management for an object, optionally filtered by tag
        Can return None
        """
        content_type = ContentType.objects.get_for_model(obj)
        query = self.filter(
            content_type=content_type,
            object_id=obj.pk
        )
            
        if tag:
            query = query.filter(tags__name=tag)
            
        return query.first()

    def get_or_create_for_object(self, obj, tag: Optional[str] = None):
        """
        Get or create audit management for an object, optionally with a tag
        Returns (audit_management, created) tuple
        """
        content_type = ContentType.objects.get_for_model(obj)
        
        # If tag is provided, try to find existing with tag
        if tag:
            existing = self.filter(
                content_type=content_type,
                object_id=obj.pk,
                tags__name=tag
            ).first()
            
            if existing:
                return existing, False
            
        # Create new audit management
        audit_management = self.create(
            content_type=content_type,
            object_id=obj.pk,
        )
        
        # Add tag if provided
        if tag:
            audit_management.add_tag(tag)
            
        return audit_management, True

class AuditManagement(models.Model):
    objects = AuditManagementManager()
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.CharField(max_length=255, null=True)  # Changed to CharField to support UUIDs
    content_object = GenericForeignKey('content_type', 'object_id')
    tags = models.ManyToManyField(
        AMTag,
        related_name='audit_managements',
        blank=True,
        verbose_name=_("标签")
    )
    
    auditor = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        null=True,
        on_delete=models.SET_NULL,
        verbose_name=_("审核者"),
    )
    status = default_audit_status_field
    comment = models.TextField(verbose_name=_('审核备注'), default='', blank=True)
    updated_at = models.DateField(auto_now=True)

    @property
    def status_verbose(self):
        return AUDIT_STATUS(self.status).label

    class Meta:
        indexes = [
            models.Index(fields=["content_type", "object_id"]),
        ]
        default_permissions = []
        db_table = 'audit_management'
        verbose_name = _('审核管理')
        verbose_name_plural = verbose_name

    def save(self, *args, **kwargs):
        super().save(*args, **kwargs)
        AuditRecord.objects.create(
            audit_management=self,
            status=self.status,
            comment=self.comment,
            auditor=self.auditor
        )

    def add_tag(self, tag_name):
        """
        Add a tag by name (creates if doesn't exist)
        Note since `tags` field is ManyToMany field, it is unnecessary to have `am.save()`
        """
        tag, _ = AMTag.objects.get_or_create(name=tag_name)
        self.tags.add(tag)

    def remove_tag(self, tag_name):
        """Remove a tag by name"""
        self.tags.remove(AMTag.objects.get(name=tag_name))


class AuditRecord(models.Model):
    """Track individual audit actions"""
    audit_management = models.ForeignKey(
        AuditManagement,
        on_delete=models.CASCADE,
        related_name="records"
    )
    auditor = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        null=True,
        on_delete=models.SET_NULL,
        verbose_name=_("审核者"),
    )
    status = default_audit_status_field
    comment = models.TextField(blank=True, default="")
    created_at = models.DateField(auto_now_add=True)
    
    class Meta:
        default_permissions = []
        db_table = 'audit_records'
        verbose_name = _('审核日志')
        verbose_name_plural = verbose_name
